// Copyright 2011 Bryan McKelvey, MIT License

/**
 * @fileoverview The Investor singleton and the methods available to it
 * @author bryan.mckelvey@gmail.com (McKelvey Bryan)
 */

/**
 * This class represents an individual investor, who may have a collection of
 * portfolios, and within those a collection of quotes
 * @constructor
 */
var Investor = (function(){
  var portfolios = [];
  var currentIndex = 0;
  var frequency = 15000;
  var timeout;
	
	return {
		/**
		 * Adds a portfolio
		 * @param {Portfolio} portfolio The portfolio to be added
		 * @returns The current object
		 * @type Investor
		 */
		add: function(portfolio){
			portfolios.push(portfolio);
			return this;
		},

		clear: function(){
		  portfolios = [new Portfolio("Portfolio", 0, false)];
		  loadTickers();
		  save();
			return this;
		},
		
		/**
		 * Retrieves the number of portfolios assigned to the Investor object
		 * @returns The number of portfolios
		 * @type Number
		 */
		count: function(){
			return portfolios.length;
		},

		/**
		 * Retrieves the current portfolio
		 * @returns The current portfolio
		 * @type Portfolio
		 */
		current: function(){
			var iter = 0;
			while (portfolios[currentIndex] == undefined && currentIndex > 0 && iter < 50) {
				currentIndex--;
				iter++;
			}
			return portfolios[currentIndex];
		},
		
		/**
		 * Removes the trigger condition from all related quotes
		 * @param {string} secid The security ID shown in the notification window
		 * @param {string} trigger The specific trigger condition to remove
		 * @returns The current object
		 * @type Investor
		 */
		disarm: function(secid, trigger){
			$.each(portfolio, function(i, portfolio){
				$.each(portfolio.quotes, function(j, quote){
					if (quote.secid === secid) {
						quote.trigger = quote.trigger.replace(trigger, '').replace(/^\,|\,$/g, "");
						quote.triggered = false;
						quote.checkTrigger();
					}
				});
			});
			return this;
		},		
		
		drawTable: function(contextNode){
			Investor.current().drawTable(contextNode);
		},
		
		/**
		 * Loads the settings for portfolios and quotes into the Investor object
		 * @returns The current object
		 * @type Investor
		 */
		load: function(){
			var parentScope = this;
			var i = 0;
			$.each(Settings.portfolios(), function(name, quotes){
				var p = new Portfolio(name, i++, false);
				$.each(quotes, function(key, data){
					var q = new Quote(data.secid, data.source, data.count,
						data.pricePaid, data.decimals, data.trigger);
					p.add(q);
				});
				parentScope.add(p);
			});
			this.loadTickers();
			return this;
		},

		/**
		 * Calls the loadTicker method in each {@link Quote} object
		 * @returns The current object
		 * @type Investor
		 * @see Quote#loadTicker
		 */
		loadTickers: function(){
		  // Need to scope for use in timeout function
		  var parentScope = this;
		  clearTimeout(timeout);

			$.each(portfolios, function(i, portfolio){
				$.each(portfolio.quotes, function(j, quote){
					quote.loadTicker();
				});
			});	
		
		  timeout = setTimeout(function() { parentScope.loadTickers(); }, frequency);
		},
		
		reset: function(){
			var p = new Portfolio('Portfolio', 0, false);
			var resetfolio = [
				['WFC', 'bloomberg', 10, 30, 2, ''],
				['8604:JP', 'bloomberg', 0, 0, 0, ''],
				['SPX:IND', 'bloomberg', 0, 0, 2, ''],
				['EURUSD:IND', 'bloomberg', 0, 0, 2, '>=1.3,>=1.4,>=1.5'],
				['US0003M:IND', 'bloomberg', 0, 0, 3, ''],
				['USSWAP10:IND', 'bloomberg', 0, 0, 3, ''],
				['CGRC1E5:IND', 'bloomberg', 0, 0, 2, ''],
				['DXY:IND', 'bloomberg', 0, 0, 1, ''],
				['GOOG', 'google', 5, 400, 2, ''],
				['.FTSE', 'google', 0, 0, 2, ''],
				['YHOO', 'yahoo', 5, 30, 2, ''],
				['^VIX', 'yahoo', 0, 0, 2, ''],
				['GCH11.CMX', 'yahoo', 0, 0, 2, ''],
				['$INDU', 'quote', 0, 0, 2, '']
			];
			
			$.each(resetfolio, function(i, data){
				p.add(new Quote(data[0], data[1], data[2],
					data[3], data[4], data[5]));
			});
			
			portfolios = [p];
			Investor.loadTickers();
			Investor.save();
			return this;
		},
		
		/**
		 * Removes the portfolio assigned to a specific index
		 * @param {Number} index
		 * @returns The current object
		 * @type Investor
		 */
		remove: function(index){
			portfolios.splice(index, 1);
			return this;
		},
		
		/**
		 * Saves the portfolios and quotes assigned to the Investor object to local
		 * storage
		 * @returns The current object
		 * @type Investor
		 */
		save: function(){
		  var saveJSON = {};
			$.each(portfolios, function(index, portfolio){
		    saveJSON[portfolio.name] = [];
				$.each(portfolio.quotes, function(index, quote){
		      saveJSON[portfolio.name].push({
		        secid: quote.secid,
		        source: quote.source,
		        count: quote.count,
		        pricePaid: quote.pricePaid,
		        decimals: quote.decimals,
		        trigger: quote.trigger
		      });
				});
			});
		  Settings.portfolios(saveJSON);
			return this;
		},
		
		createDropDown: function(contextNode, tableContextNode, editable) {
		  // Clear context node
		  if (contextNode.hasChildNodes()) {
		    while (contextNode.childNodes.length >= 1) {
		      contextNode.removeChild(contextNode.firstChild);
		    }
		  }
		
		  var select = document.createElement("select");
		  var _this = this;
		  select.onchange = function() {
		    var answer = true;
		    if (editable) {
		      answer = confirm("Note that any changes you have made will be lost if you haven't saved.");
		    }
		    if (answer) {
		      if (this.value === "New...") {
		        var name = prompt("Name your new portfolio", "Portfolio " + (this.selectedIndex + 1));
		        if (name != null) {
		          var p = new Portfolio(name, this.selectedIndex, false);
		          _this.add(p);
		          _this.currentIndex = _this.portfolios.length - 1;
		          if (editable) {
		            _this.current().editTable(tableContextNode);
		          } else {
		            _this.current().drawTable(tableContextNode);
		          }
		          _this.createDropDown(contextNode, tableContextNode, editable);
		        }
		      } else {
		        _this.currentIndex = this.selectedIndex;
		        if (editable) {
		          _this.current().editTable(tableContextNode);
		        } else {
		          _this.current().drawTable(tableContextNode);
		        }
		      }
		    }
		  }
			$.each(portfolios, function(index, portfolio){
		    $(select).append($('<option>').val(index === currentIndex).text(portfolio.name));
			});
		  
		  if (editable) {
		    $(select).append($('<option>').text('New...'));
		  }
		
		  contextNode.appendChild(select);
		}
	}
})();

Investor.load();
